#include "Persistor.h"

Persistor::Persistor() {
}

std::stringstream Persistor::logging;

std::string Persistor::scenariosPath = XML_PATH;
std::list<std::string> Persistor::scenarioNames;
std::list<Scenario*> Persistor::scenarios;
std::list<Scenario*>::iterator Persistor::it_scenario;
std::list<ScenarioElement*> Persistor::scrollBarElements;
std::list<ScenarioElement*>::iterator Persistor::it_scenarioElement;

std::list<string> Persistor::getScenarioNames() {
	std::list<string> result;

	char* c_scenariosPath = new char[scenariosPath.size() + 1];strcpy
	(c_scenariosPath, scenariosPath.c_str());
	TiXmlDocument doc(c_scenariosPath);
	//verifica si se pudo leer el archivo xml
	if (doc.LoadFile()) {
		TiXmlElement* root = doc.RootElement();
		//recorro todos los escenarios definidos en el xml
		TiXmlElement* scenariosTag = root->FirstChildElement();
		TiXmlElement* scenarioTag;
		std::string scenarioName;
		for (scenarioTag = scenariosTag->FirstChildElement(); scenarioTag;
				scenarioTag = scenarioTag->NextSiblingElement()) {
			scenarioName = scenarioTag->Attribute("nombre");
			result.push_back(scenarioName);
		}
	} else {
		Logger::log("Persistor", "getScenarioNames",
				"No se puedo leer el XML de los Escenarios");
	}

	delete[] c_scenariosPath;

	return result;
}

std::list<ScenarioElement*> Persistor::getScenarioElements(
		std::string scenarioName) {
	std::list<ScenarioElement*> result;

	char* c_searchedName = new char[scenarioName.size() + 1];strcpy
	(c_searchedName, scenarioName.c_str());
	char* c_currentName;

	char* c_scenariosPath = new char[scenariosPath.size() + 1];strcpy
	(c_scenariosPath, scenariosPath.c_str());
	TiXmlDocument doc(c_scenariosPath);
	//verifica si se pudo leer el archivo xml
	if (doc.LoadFile()) {
		TiXmlElement* root = doc.RootElement();
		//recorro todos los escenarios definidos en el xml
		TiXmlElement* scenariosTag = root->FirstChildElement();
		TiXmlElement* scenarioTag;
		std::string scenarioName;
		bool found = false;
		for (scenarioTag = scenariosTag->FirstChildElement(); (scenarioTag);
				scenarioTag = scenarioTag->NextSiblingElement()) {
			scenarioName = scenarioTag->Attribute("nombre");
			c_currentName = new char[scenarioName.size() + 1];strcpy
			(c_currentName, scenarioName.c_str());
			if (strcmp(c_searchedName, c_currentName) == 0) {
				found = true;
				break;
			}
			delete[] c_currentName;
		}

		if (found) {
			logging << "Se encontraron elementos para el escenario "
					<< scenarioName;
			Logger::log("Persistor", "getScenarioElements", &logging);

			TiXmlElement* scenarioElementTag;
			std::string scenarioElementPath;
			ScenarioElement* currentScenarioElement = NULL;
			int xPos, yPos;
			for (scenarioElementTag = scenarioTag->FirstChildElement();
					scenarioElementTag;
					scenarioElementTag =
							scenarioElementTag->NextSiblingElement()) {
				scenarioElementPath = scenarioElementTag->Attribute("path");

				scenarioElementTag->Attribute("posX", &xPos);
				scenarioElementTag->Attribute("posY", &yPos);
				currentScenarioElement = new ScenarioElement(xPos, yPos, NULL,
						scenarioElementPath);
				result.push_back(currentScenarioElement);
			}
		}

	} else {
		Logger::log("Persistor", "getScenarioElements",
				"No se puedo leer el XML de los Escenarios");
	}
	delete[] c_scenariosPath;
	delete[] c_searchedName;

	logging << "Se encontraron " << result.size() << " para el escenario "
			<< scenarioName;
	Logger::log("Persistor", "getScenarioElements", &logging);
	return result;
}

std::string Persistor::getBackground(std::string scenarioName) {
	std::string result;

	char* c_searchedName = new char[scenarioName.size() + 1];strcpy
	(c_searchedName, scenarioName.c_str());
	char* c_currentName;

	char* c_scenariosPath = new char[scenariosPath.size() + 1];strcpy
	(c_scenariosPath, scenariosPath.c_str());
	TiXmlDocument doc(c_scenariosPath);
	//verifica si se pudo leer el archivo xml
	if (doc.LoadFile()) {
		TiXmlElement* root = doc.RootElement();
		//recorro todos los escenarios definidos en el xml
		TiXmlElement* scenariosTag = root->FirstChildElement();
		TiXmlElement* scenarioTag;
		std::string scenarioName;
		bool found = false;
		for (scenarioTag = scenariosTag->FirstChildElement();
				scenarioTag && !found;
				scenarioTag = scenarioTag->NextSiblingElement()) {
			scenarioName = scenarioTag->Attribute("nombre");
			c_currentName = new char[scenarioName.size() + 1];strcpy
			(c_currentName, scenarioName.c_str());
			if (strcmp(c_searchedName, c_currentName) == 0) {
				found = true;
				result = scenarioTag->Attribute("fondo");
			}
			delete[] c_currentName;
		}

	} else {
		Logger::log("Persistor", "getScenarioElements",
				"No se puedo leer el XML de los Escenarios");
	}
	delete[] c_scenariosPath;
	delete[] c_searchedName;

	return result;

}

std::list<ScenarioElement*> Persistor::getScrollBarElements() {
	list<ScenarioElement*> result;

	char* c_scenariosPath = new char[scenariosPath.size() + 1];strcpy
	(c_scenariosPath, scenariosPath.c_str());
	TiXmlDocument doc(c_scenariosPath);
	//verifica si se pudo leer el archivo xml
	if (doc.LoadFile()) {
		TiXmlElement* root = doc.RootElement();
		//recorro todos los escenarios definidos en el xml
		TiXmlElement* scenariosTag = root->FirstChildElement();

		int xPos, yPos;

		//recorro todos los objetos definidos en el xml
		ScenarioElement* scrollBarElement = NULL;
		TiXmlElement* scrollBarElementsTag = scenariosTag->NextSiblingElement();
		TiXmlElement* scrollBarElementTag;
		for (scrollBarElementTag = scrollBarElementsTag->FirstChildElement();
				scrollBarElementTag;
				scrollBarElementTag = scrollBarElementTag->NextSiblingElement()) {
			scrollBarElementTag->Attribute("posX", &xPos);
			scrollBarElementTag->Attribute("posY", &yPos);

			scrollBarElement = new ScenarioElement(xPos, yPos, NULL,
					scrollBarElementTag->Attribute("path"));
			result.push_back(scrollBarElement);
		}
	} else {
		Logger::log("Persistor", "getScrollBarElements",
				"No se puedo leer el XML de los Escenarios");
	}

	delete[] c_scenariosPath;

	return result;
}

void Persistor::createScenario(std::string scenarioName) {
	read();
	Scenario* scenario = new Scenario(scenarioName, "./trunk/res/img/escenarios/green.bmp", NULL);
	scenarios.push_back(scenario);
	write();
}

void Persistor::deleteScenario(std::string scenarioName) {
	char* c_searchedName = new char[scenarioName.size() + 1];strcpy
	(c_searchedName, scenarioName.c_str());

	char* c_currentScenarioName;

	read();

	std::string currentScenarioName;
	for(it_scenario = scenarios.begin(); it_scenario!=scenarios.end();it_scenario++){
		currentScenarioName = ((Scenario*)*it_scenario)->getName();
		c_currentScenarioName = new char[currentScenarioName.size() +1];
		strcpy(c_currentScenarioName, currentScenarioName.c_str());

		if(strcmp(c_searchedName, c_currentScenarioName) == 0){
			it_scenario = scenarios.erase(it_scenario);

		}
		delete[] c_currentScenarioName;
	}

	write();
}

void Persistor::updateScenarioElements(std::string scenarioName,
		std::list<ScenarioElement*> scenarioElements) {

	char* c_searchedName = new char[scenarioName.size() + 1];strcpy
	(c_searchedName, scenarioName.c_str());

	char* c_currentScenarioName;

	read();

	Scenario* scenario = NULL;
	std::string currentScenarioName;
	for (it_scenario = scenarios.begin(); it_scenario != scenarios.end();
			it_scenario++) {
		currentScenarioName = ((Scenario*) *it_scenario)->getName();
		c_currentScenarioName = new char[currentScenarioName.size() + 1];strcpy
		(c_currentScenarioName, currentScenarioName.c_str());

		if (strcmp(c_searchedName, c_currentScenarioName) == 0) {
			scenario = (Scenario*) *it_scenario;
		}
		delete[] c_currentScenarioName;
	}

	if (scenario != NULL) {
		scenario->getElements()->clear();
		for (it_scenarioElement = scenarioElements.begin();
				it_scenarioElement != scenarioElements.end();
				it_scenarioElement++) {
			scenario->getElements()->push_back(*it_scenarioElement);
		}

	}

	write();
}

void Persistor::updateScenario(std::string scenarioName, std::string background,
		std::list<ScenarioElement*> scenarioElements) {

	char* c_searchedName = new char[scenarioName.size() + 1];strcpy
	(c_searchedName, scenarioName.c_str());

	char* c_currentScenarioName;

	read();

	Scenario* scenario = NULL;
	std::string currentScenarioName;
	for (it_scenario = scenarios.begin(); it_scenario != scenarios.end();
			it_scenario++) {
		currentScenarioName = ((Scenario*) *it_scenario)->getName();
		c_currentScenarioName = new char[currentScenarioName.size() + 1];strcpy
		(c_currentScenarioName, currentScenarioName.c_str());

		if (strcmp(c_searchedName, c_currentScenarioName) == 0) {
			scenario = (Scenario*) *it_scenario;
		}
		delete[] c_currentScenarioName;
	}

	if (scenario != NULL) {
		scenario->setBackground(background);
		scenario->getElements()->clear();
		for (it_scenarioElement = scenarioElements.begin();
				it_scenarioElement != scenarioElements.end();
				it_scenarioElement++) {
			scenario->getElements()->push_back(*it_scenarioElement);
		}

	}

	write();

}

void Persistor::updateScenarioBackground(std::string scenarioName,
		std::string background) {

	char* c_searchedName = new char[scenarioName.size() + 1];strcpy
	(c_searchedName, scenarioName.c_str());

	char* c_currentScenarioName;

	read();

	Scenario* scenario = NULL;
	std::string currentScenarioName;
	for(it_scenario = scenarios.begin(); it_scenario!=scenarios.end();it_scenario++){
			currentScenarioName = ((Scenario*)*it_scenario)->getName();
			c_currentScenarioName = new char[currentScenarioName.size() +1];
			strcpy(c_currentScenarioName, currentScenarioName.c_str());

			if(strcmp(c_searchedName, c_currentScenarioName) == 0){
				scenario = (Scenario*)*it_scenario;
				scenario->setBackground(background);
			}
			delete[] c_currentScenarioName;
		}

		write();
}

void Persistor::writeScenarios(TiXmlNode* scenariosNode) {

	Scenario* currentScenario = NULL;
	for (it_scenario = scenarios.begin(); it_scenario != scenarios.end();
			it_scenario++) {
		currentScenario = (Scenario*) *it_scenario;
		writeScenario(scenariosNode, currentScenario);
	}

}

void Persistor::writeScenario(TiXmlNode* scenariosNode, Scenario* scenario) {
	char* c_name = new char[scenario->getName().size() + 1];strcpy(c_name, scenario->getName().c_str());
	char* c_background = new char[scenario->getBackground().size() +1];strcpy(c_background, scenario->getBackground().c_str());

	TiXmlElement* scenarioTag = new TiXmlElement("ESCENARIO");
	TiXmlNode* scenarioNode = scenariosNode->LinkEndChild(scenarioTag);
	TiXmlElement* scenarioElement = scenarioNode->ToElement();
	scenarioElement->SetAttribute("nombre", c_name);
	scenarioElement->SetAttribute("fondo", c_background);

	delete[] c_name;
	delete[] c_background;

	writeScenarioElements(scenarioNode, scenario->getElements());
}

void Persistor::writeScenarioElements(TiXmlNode* scenarioElementsNode,
		std::list<ScenarioElement*>* scenarioElements) {

	if (scenarioElements == NULL) {
		return;
	}
	ScenarioElement* currentScenarioElement = NULL;
	for (it_scenarioElement = scenarioElements->begin();
			it_scenarioElement != scenarioElements->end();
			it_scenarioElement++) {
		currentScenarioElement = (ScenarioElement*) *it_scenarioElement;

		writeScenarioElement(scenarioElementsNode, currentScenarioElement);

	}

}

void Persistor::writeScenarioElement(TiXmlNode* currentScenarioNode,
		ScenarioElement* scenarioElement) {
	char* c_name = new char[scenarioElement->getName().size() + 1];strcpy(c_name,scenarioElement->getName().c_str());
	char* c_path = new char[scenarioElement->getPath().size() + 1];strcpy(c_path,scenarioElement->getPath().c_str());

	TiXmlElement* scenarioElementTag = new TiXmlElement("OBJETO");
	TiXmlElement* scenarioElementTagElement = currentScenarioNode->LinkEndChild(
			scenarioElementTag)->ToElement();
	scenarioElementTagElement->SetAttribute("nombre", c_name);
	scenarioElementTagElement->SetAttribute("path", c_path);
	scenarioElementTagElement->SetAttribute("posX", scenarioElement->getXPos());
	scenarioElementTagElement->SetAttribute("posY", scenarioElement->getYPos());

	delete[] c_name;
	delete[] c_path;
}

void Persistor::read() {

	char* c_scenariosPath = new char[scenariosPath.size() + 1];strcpy(c_scenariosPath,scenariosPath.c_str());
	TiXmlDocument doc(c_scenariosPath);
	//verifica si se pudo leer el archivo xml
	if (doc.LoadFile()) {
		TiXmlElement* root = doc.RootElement();
		//recorro todos los escenarios definidos en el xml
		TiXmlElement* scenariosTag = root->FirstChildElement();
		TiXmlElement* scenarioTag;

		std::string scenarioName;
		std::string scenarioBackground;
		Scenario* currentScenario = NULL;
		std::list<ScenarioElement*>* currentScenarioElements = NULL;
		TiXmlElement* scenarioElementTag;
		std::string scenarioElementPath;
		int xPos, yPos;
		ScenarioElement* currentScenarioElement = NULL;
		for(scenarioTag = scenariosTag->FirstChildElement(); scenarioTag; scenarioTag = scenarioTag->NextSiblingElement()) {
			scenarioName = scenarioTag->Attribute("nombre");
			scenarioBackground = scenarioTag->Attribute("fondo");

			//cargo la lista de elememtos del escenario actual
			currentScenarioElements = new list<ScenarioElement*>();
			for (scenarioElementTag = scenarioTag->FirstChildElement(); scenarioElementTag; scenarioElementTag = scenarioElementTag->NextSiblingElement()) {
				scenarioElementPath = scenarioElementTag->Attribute("nombre");

				scenarioElementTag->Attribute("posX",&xPos);
				scenarioElementTag->Attribute("posY",&yPos);
				currentScenarioElement = new ScenarioElement(xPos, yPos, NULL, scenarioElementPath);
				currentScenarioElements->push_back(currentScenarioElement);
			}

			currentScenario = new Scenario(scenarioName,scenarioBackground, currentScenarioElements);
			scenarios.push_back(currentScenario);
			scenarioNames.push_back(scenarioName);
		}

		//recorro todos los objetos definidos en el xml
		ScenarioElement* scrollBarElement = NULL;
		TiXmlElement* scrollBarElementsTag = scenariosTag->NextSiblingElement();
		TiXmlElement* scrollBarElementTag;
		for(scrollBarElementTag = scrollBarElementsTag->FirstChildElement(); scrollBarElementTag; scrollBarElementTag = scrollBarElementTag->NextSiblingElement()) {
			scrollBarElementTag->Attribute("posX",&xPos);
			scrollBarElementTag->Attribute("posY",&yPos);

			scrollBarElement = new ScenarioElement(xPos, yPos, NULL, scrollBarElementTag->Attribute("path"));
			scrollBarElements.push_back(scrollBarElement);
		}
	}
	else {
		Logger::log("Persistor","Read", "No se puedo leer el XML de los Escenarios");
	}

	delete[] c_scenariosPath;
}

void Persistor::write() {

	TiXmlDocument doc;

	char* c_scenariosPath = new char[scenariosPath.size() + 1];strcpy
	(c_scenariosPath, scenariosPath.c_str());

	if (doc.SaveFile(c_scenariosPath)) {

		//creo el tag DISEÑO_ESCENARIO
		TiXmlElement * root = new TiXmlElement("DISEÑO_ESCENARIO");
		TiXmlNode* scenarioDesignNode = doc.LinkEndChild(root);

		//creo el tag ESCENARIOS
		TiXmlElement * scenariosTag = new TiXmlElement("ESCENARIOS");
		TiXmlNode* scenariosNode = scenarioDesignNode->LinkEndChild(
				scenariosTag);
		writeScenarios(scenariosNode);

		//creo el tag OBJETOS que son los que aparecen en el scroll selector
		TiXmlElement * scenarioElementsTag = new TiXmlElement("OBJETOS");
		TiXmlNode* scenarioElementsNode = scenarioDesignNode->LinkEndChild(
				scenarioElementsTag);
		writeScenarioElements(scenarioElementsNode, &scrollBarElements);

		//aplico los cambios, guardando el archivo
		doc.SaveFile(c_scenariosPath);
	} else {
		Logger::log("Persistor", "write",
				"No se pudo escribir el XML de escenarios");
	}

	delete[] c_scenariosPath;
	freeTemporalMemory();
}

void Persistor::freeTemporalMemory() {
	scenarioNames.clear();
	scenarios.clear();
	scrollBarElements.clear();
}

Persistor::~Persistor() {

}

